package com.qmx.qmxapp.okhttp;

import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import com.qmx.qmxapp.bean.RegErrorMsg;
import com.qmx.qmxapp.utils.EStringUtils;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.MultipartBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * Created by lzs on 2016/1/27.
 */
public class OkUploadHttpHelper {

    private static OkHttpClient okHttpClient;

    private static OkUploadHttpHelper mInstance;

    private Gson mGson;

    private Handler mHandler;

    private Context mContext;

    private OkUploadHttpHelper() {
        okHttpClient = new OkHttpClient();
        okHttpClient.setConnectTimeout(30, TimeUnit.SECONDS);
        okHttpClient.setReadTimeout(30, TimeUnit.SECONDS);
        okHttpClient.setWriteTimeout(30, TimeUnit.SECONDS);

        mGson = new Gson();
        mHandler = new Handler(Looper.getMainLooper());
    }

    static {
        mInstance = new OkUploadHttpHelper();
    }

    public static OkUploadHttpHelper getInstance() {
        return mInstance;
    }


    public void upload(String url, Context context, File file, String param, final OnProgressListener progressListener, BaseCallback callback) {
        mContext = context;
        Request.Builder builder = new Request.Builder();
        builder.url(url);
        for (Map.Entry<String, Object> entry : getDefaultHeadParams(context).entrySet()) {
            builder.addHeader(entry.getKey(), entry.getValue().toString());
        }
//        builder.addHeader("Accept-Encoding", "identity");
        MediaType MEDIA_TYPE_PNG = MediaType.parse("image/jpg");

        RequestBody requestBody = new MultipartBuilder()
                .type(MultipartBuilder.FORM)
                .addFormDataPart(param, file.getName(), RequestBody.create(MEDIA_TYPE_PNG, file))
                .build();

        ProgressRequestBody progressRequestBody = new ProgressRequestBody(requestBody, new ProgressListener() {
            @Override
            public void onProgress(final long currentBytes, final long contentLength, final boolean done) {
                final int progress = (int) ((float) currentBytes / (float) contentLength * 100);
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        progressListener.onProgress(progress);
                    }
                });
            }
        });

        Request request = builder
                .url(url)
                .post(requestBody)
                .build();

//        builder.post(progressRequestBody);
//
//        Request request = builder.build();

        doRequest(request, callback);
    }

    public void download(String url) {

    }


    public void doRequest(Request request, final BaseCallback callback) {

        callback.onRequestBefore(request);


        okHttpClient.newCall(request).enqueue(new Callback() {

            @Override
            public void onFailure(Request request, IOException e) {
                callback.onFailure(request, e);
            }

            @Override
            public void onResponse(Response response) throws IOException {
                callback.onResponse(response);

                if (response.isSuccessful()) {
                    String resultStr = response.body().string();
                    Log.d("okhttp", "=====>response_body:" + resultStr);
                    if (callback.mType == String.class) {
                        callbackSuccess(callback, response, resultStr);
                    } else {
                        try {
                            Object object = mGson.fromJson(resultStr, callback.mType);
                            callbackSuccess(callback, response, object);
                        } catch (JsonParseException e) {
                            callbackError(callback, response, response.code(), resultStr, e);
                        }
                    }
                } else {
                    String resultStr = response.body().string();
                    Log.d("okhttp", "error=====>response_body:" + resultStr);
                    callbackError(callback, response, response.code(), resultStr, null);
                }
            }
        });

    }

    private Request buildRequestByJson(String url, String json, HttpMethodType methodType) {
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");

        Request.Builder builder = new Request.Builder();
        builder.url(url);

        if (methodType == HttpMethodType.GET) {
            builder.get();
        } else if (methodType == HttpMethodType.POST) {
            RequestBody body = RequestBody.create(JSON, json);
            builder.post(body);
        } else if (methodType == HttpMethodType.PUT) {
            RequestBody body = RequestBody.create(JSON, json);
            builder.put(body);
        }

        return builder.build();
    }


    private Request buildRequestJsonProtect(String url, Map<String, Object> headParams, String json, HttpMethodType methodType) {
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");

        Request.Builder builder = new Request.Builder();

        builder.url(url);

        if (null != headParams) {
            for (Map.Entry<String, Object> entry : headParams.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue().toString());
                Log.d("TAG", entry.getKey() + ":" + entry.getValue().toString());
            }
        }

        if (methodType == HttpMethodType.GET) {
            builder.get();
        } else if (methodType == HttpMethodType.POST) {
            RequestBody body = RequestBody.create(JSON, json);
            builder.post(body);
        } else if (methodType == HttpMethodType.PUT) {
            RequestBody body = RequestBody.create(JSON, json);
            builder.put(body);
        } else if (methodType == HttpMethodType.DELETE) {
            if (null == json) {
                builder.delete();
            } else {
                RequestBody body = RequestBody.create(JSON, json);
                builder.delete(body);
            }
        }

        return builder.build();
    }

    private Request buildRequest(String url, Map<String, String> params, HttpMethodType methodType) {
        return buildRequestWithHeaderParams(url, null, params, methodType);
    }

    private Request buildRequestWithHeaderParams(String url, Map<String, Object> headParams, Map<String, String> params, HttpMethodType methodType) {
        Request.Builder builder = new Request.Builder();

        builder.url(url);

        if (null != headParams) {
            for (Map.Entry<String, Object> entry : headParams.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue().toString());
            }
        }

        if (methodType == HttpMethodType.GET) {
            builder.get();
        } else if (methodType == HttpMethodType.POST) {
            RequestBody body = buildFormData(params);
            builder.post(body);
        }

        return builder.build();
    }


    private RequestBody buildFormData(Map<String, String> params) {
        FormEncodingBuilder builder = new FormEncodingBuilder();
        if (params != null) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                builder.add(entry.getKey(), entry.getValue());
            }
        }

        return builder.build();
    }

    private void callbackSuccess(final BaseCallback callback, final Response response, final Object object) {
        //callback.onSuccess(response, object);
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                callback.onSuccess(response, object);
            }
        });
    }

    private void callbackError(final BaseCallback callback, final Response response, final int code, final String msg, final Exception e) {
        String resMsg = null;

        if (EStringUtils.isNotBlank(msg)) {
            try {
                RegErrorMsg responseErrorMsg = mGson.fromJson(msg, RegErrorMsg.class);
                resMsg = responseErrorMsg.getMessage();
            } catch (JsonParseException jsonException) {
                resMsg = "服务器忙,请稍后再试";
            }
        }

        final String finalResMsg = resMsg;

        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (null != mContext && EStringUtils.isNotBlank(finalResMsg) && finalResMsg.equals("未授权")) {
                    Activity activity = (Activity) mContext;
                    if (null != activity) {
//                        ((HApplication) activity.getApplication()).finishAllActivity();
                        //                        Intent intent = new Intent(activity, LoginActivity.class);
                        //                        mContext.startActivity(intent);
                    }
                }
                callback.onError(response, code, finalResMsg, e);
            }
        });
    }

    private Map<String, Object> getDefaultHeadParams(Context context) {
        //        SharedPreferences share= context.getSharedPreferences(Constant.SP_ETAO_INFO, Context.MODE_PRIVATE);
        //        String token = share.getString("accessToken", "");

        long timestamp = System.currentTimeMillis() / 1000;

        Map<String, Object> headParams = new HashMap<String, Object>();
        //        headParams.put("Authorization", token);
        //        headParams.put("clientId", Constant.CLIENTID);
        //        headParams.put("timestamp", timestamp);
        //        headParams.put("clientSecret", Md5Util.md5(Constant.CLIENTSECRET + timestamp));

        return headParams;
    }

    enum HttpMethodType {
        GET,
        POST,
        PUT,
        DELETE
    }
}
